package cn.cytong.nk0713.utils.nutz;

import org.nutz.dao.Chain;
import org.nutz.dao.Sqls;
import org.nutz.dao.entity.Record;
import org.nutz.dao.impl.NutDao;
import org.nutz.dao.sql.Criteria;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.sql.SqlCallback;

import java.util.List;

/**
 * 封装了一些快捷方法的dao对象，sql语句中直接使用?变量占位符，参数会自动按顺序进行绑定。
 * 以fetch开头的方法返回单条记录，以query开头的方法返回记录列表
 */
public class CustomisedNutDao {
    private NutDao dao;

    public CustomisedNutDao(NutDao dao) {
        this.dao = dao;
    }

    public String fetchString(String sqlSource, Object... params) {
        Sql sql = buildAndExecute(sqlSource, Sqls.callback.str(), params);
        return sql.getObject(String.class);
    }

    public List<String> queryString(String sqlSource, Object... params) {
        Sql sql = buildAndExecute(sqlSource, Sqls.callback.strList(), params);
        return sql.getList(String.class);
    }

    public Long fetchLong(String sqlSource, Object... params) {
        Sql sql = buildAndExecute(sqlSource, Sqls.callback.longValue(), params);
        return sql.getObject(Long.class);
    }

    public List<Long> queryLong(String sqlSource, Object... params) {
        Sql sql = buildAndExecute(sqlSource, Sqls.callback.longs(), params);
        return sql.getList(Long.class);
    }

    public Record fetchRecord(String sqlSource, Object... params) {
        Sql sql = buildAndExecute(sqlSource, Sqls.callback.record(), params);
        return sql.getObject(Record.class);
    }

    public List<Record> queryRecord(String sqlSource, Object... params) {
        Sql sql = buildAndExecute(sqlSource, Sqls.callback.records(), params);
        return sql.getList(Record.class);
    }

    public List<Record> queryPageRecord(String sqlSource, int pageNum, int rowsPerPage, Object... params) {
        Sql sql = buildAndExecute(sqlSource, pageNum, rowsPerPage, Sqls.callback.records(), params);
        return sql.getList(Record.class);
    }

    /**
     * 查询单条记录，直接使用Cnd作为条件，sql语句中
     *
     * @param sqlSource 查询语句，where条件部分直接以变量$condition替换，例如select * from User $condition
     * @param condition Criteria查询条件
     * @return Record list
     */
    public Record fetchRecordWithCriteria(String sqlSource, Criteria condition) {
        Sql sql = Sqls.fetchRecord(sqlSource);
        sql.setCondition(condition);
        sql.setPager(condition.getPager());
        execute(sql);
        return sql.getObject(Record.class);
    }

    public Record fetchTableRecord(String tableName, String whereCause, Object... params) {
        Sql sql = buildAndExecute(String.format("select * from %s where %s", tableName, whereCause), Sqls.callback.record(), params);
        return sql.getObject(Record.class);
    }

    public List<Record> queryTableRecord(String tableName, String whereCause, Object... params) {
        Sql sql = buildAndExecute(String.format("select * from %s where %s", tableName, whereCause), Sqls.callback.records(), params);
        return sql.getList(Record.class);
    }

    public List<Record> queryTablePageRecord(String tableName, int pageNum, int rowsPerPage, String whereCause, Object... params) {
        Sql sql = buildAndExecute(String.format("select * from %s where %s", tableName, whereCause), pageNum, rowsPerPage, Sqls.callback.records(), params);
        return sql.getList(Record.class);
    }

    /**
     * 执行update、insert等命令
     */
    public void executeUpdate(String sqlSource, Object... params) {
        buildAndExecute(sqlSource, null, params);
    }

    public void execute(Sql... sqls) {
        dao.execute(sqls);
    }

    public void insert(String tableName, Chain chain) {
        dao.insert(tableName, chain);
    }

    public BatchSql createBatchSql(String sqlSource) {
        return new BatchSql(sqlSource);
    }

    public void executeBatch(BatchSql batchSql) {
        if (batchSql.getBatchSize() > 0) {
            dao.execute(batchSql.getSql());
            batchSql.clearBatch();
        }
    }

    private Sql buildAndExecute(String sqlSource, SqlCallback callback, Object... params) {
        Sql sql = SqlUtility.buildWithParams(sqlSource, params);
        if (callback != null) {
            sql.setCallback(callback);
        }
        dao.execute(sql);
        return sql;
    }

    private Sql buildAndExecute(String sqlSource, int pageNum, int rowsPerPage, SqlCallback callback, Object... params) {
        Sql sql = SqlUtility.buildWithParams(sqlSource, params);
        sql.setPager(dao.createPager(pageNum, rowsPerPage));
        if (callback != null) {
            sql.setCallback(callback);
        }
        dao.execute(sql);
        return sql;
    }

    public NutDao getBaseDao() {
        return dao;
    }
}

